Skip to main content

React Native Swipe History Implementation Plan

Date: January 15, 2025
Objective: Implement comprehensive swipe history feature for React Native with table-like interface and swipe-to-action UX


📋 Current Backend Context Analysis

✅ Available Backend APIs

1. GET /api/swipes - Comprehensive Swipe History

  • Full feature set available: pagination, filtering, search, sorting
  • Advanced filters: date range, score range, genres, release year, liked/skipped status
  • Sorting options: timestamp, title, score, release_year (asc/desc)
  • Pagination: configurable page size (1-50), total count included
  • Response format:
    {
    swipes: SwipeWithDetails[],
    pagination: { page, limit, total, totalPages },
    filters: SwipeFilters // Applied filters for reference
    }

2. PUT /api/swipes/[id] - Update Swipe

  • Editable fields: liked, score, skipped
  • Validation: mutual exclusivity (can't be both liked and skipped)
  • Score range: 0-10 with decimal support
  • Ownership verification: only user's own swipes

3. DELETE /api/swipes/[id] - Delete Swipe

  • Soft delete available: removes from user's history
  • Ownership verification: secure deletion
  • Cache invalidation: automatic React Query cache updates

✅ Rich Data Available (SwipeWithDetails)

interface SwipeWithDetails {
// Swipe metadata
id: string
user_id: string
tmdb_id: number
liked: boolean | null
score: number | null
skipped: boolean
timestamp: string
created_at: string
updated_at: string

// Movie details (fully populated)
title: string
overview: string | null
poster_url: string | null
backdrop_url: string | null
release_date: string | null
release_year: number | null
genres: Array<{ id: number; name: string }> | null
vote_average: number | null
vote_count: number | null
runtime: number | null

// Computed fields
swipe_status: "liked" | "skipped" | "disliked" | "unrated"
score_category: "high" | "medium" | "low" | "very_low" | "unrated"
}

🎯 React Native Implementation Plan

Phase 1: Core List Implementation

1.1 FlatList-Based Table Component

// components/SwipeHistoryList.tsx
interface SwipeHistoryListProps {
filter?: "liked" | "skipped" | "all"
searchQuery?: string
sortBy?: "timestamp" | "title" | "score" | "release_year"
sortOrder?: "asc" | "desc"
}

// Key features:
- FlatList with optimized rendering
- Pull-to-refresh support
- Infinite scroll pagination
- Loading skeletons
- Empty states with contextual messaging

1.2 Swipe History Row Component

// components/SwipeHistoryRow.tsx
- Movie poster (64x96px with fallback)
- Title + release year
- Status badge (Liked/Disliked/Skipped)
- Score display (stars + numeric)
- Timestamp (relative: "2 days ago")
- Swipe actions (hidden by default)

Phase 2: Swipe-to-Action UX

2.1 React Native Gesture Handler Integration

// Using react-native-gesture-handler for smooth gestures
- PanGestureHandler for horizontal swipe detection
- Animated.View for smooth motion feedback
- Haptic feedback on gesture start/complete
- Visual indicators during swipe (icons appear)

2.2 Swipe Actions Implementation

// LEFT SWIPE ONLY (iOS native pattern) reveals actions on the right side
// Actions: Edit | Delete | Quick Rate | Like Toggle | View Details

interface SwipeAction {
id: string
icon: IconName
label: string
color: string
backgroundColor: string
onPress: (swipe: SwipeWithDetails) => void
width: number
}

// Specific actions based on requirements:
- Edit (pencil icon) → Opens NativeSheet with EditSwipeForm
- Delete (trash icon) → Single destructive action (no confirmation)
- Quick Rate (star icon) → Toggle between score ranges
- Like Toggle (heart icon) → Toggle liked/disliked state
- View Details (eye icon) → Navigate to movie detail page

2.3 Gesture Animation System

// Smooth reveal animations
- translateX with spring animation
- Scale animation for revealed actions
- Opacity fade for row content during swipe
- Snap-back animation when gesture cancelled
- Completion animation when action triggered

Phase 3: Advanced Features

3.1 Search & Filter Integration

// components/SwipeHistoryFilters.tsx
- Search bar with debounced API calls
- Filter chips (Liked, Skipped, High Rated, etc.)
- Sort options (Recent, Title A-Z, Rating High-Low)
- Date range picker (This Week, This Month, Custom)
- Genre filter (multi-select)
- Quick filters (Recent Activity, Favorites)

3.2 Edit Modal

// modals/EditSwipeModal.tsx
- Movie poster + title display
- Toggle buttons: Liked / Disliked / Skipped
- Star rating component (1-10 scale)
- Save/Cancel with loading states
- Optimistic UI updates
- Error handling with retry

3.3 Delete Confirmation

// modals/DeleteSwipeModal.tsx
- Movie poster + title
- Clear warning message
- Confirm/Cancel buttons
- Loading state during deletion
- Success feedback

🛠 Technical Implementation Details

Data Management

React Query Integration

// hooks/useSwipeHistory.ts
const useSwipeHistory = (filters: SwipeFilters) => {
return useInfiniteQuery({
queryKey: ["swipes", "history", filters],
queryFn: ({ pageParam = 1 }) => fetchSwipeHistory({ ...filters, page: pageParam }),
getNextPageParam: (lastPage) =>
lastPage.pagination.page < lastPage.pagination.totalPages ? lastPage.pagination.page + 1 : undefined,
staleTime: 5 * 60 * 1000, // 5 minutes
placeholderData: keepPreviousData, // Smooth filter transitions
})
}

State Management

// stores/useSwipeHistoryStore.ts
interface SwipeHistoryStore {
filters: SwipeFilters
searchQuery: string
sortBy: SortOption
sortOrder: "asc" | "desc"
selectedTab: "liked" | "skipped" | "all"

// Actions
updateFilters: (filters: Partial<SwipeFilters>) => void
updateSearch: (query: string) => void
updateSort: (sortBy: SortOption, order: "asc" | "desc") => void
resetFilters: () => void
}

Performance Optimizations

1. FlatList Optimizations

// Optimized FlatList configuration
- getItemLayout for consistent row heights
- keyExtractor using swipe.id
- removeClippedSubviews for large lists
- initialNumToRender: 10
- maxToRenderPerBatch: 5
- windowSize: 10
- updateCellsBatchingPeriod: 50

2. Image Loading

// Optimized poster loading
- react-native-fast-image for caching
- Placeholder components during load
- Error fallbacks with movie icon
- Appropriate resize modes

3. Gesture Performance

// Smooth gesture handling
- useNativeDriver: true for animations
- Worklet functions for gesture callbacks
- Minimal re-renders during gestures
- Debounced action triggers

🎨 UX/UI Design Specifications

Visual Design

1. Row Layout

[Poster] [Title + Year + Status] [Score] [Timestamp] [→]
64x96 [Flexible width ] [Fixed] [Fixed ] [16]

2. Swipe Reveal Design

// Left swipe (destructive/edit actions)
Row content slides right, revealing:
[🗑️ Delete] [✏️ Edit] behind the row

// Right swipe (quick actions)
Row content slides left, revealing:
[⭐ Rate] [👁️ View] behind the row

3. Color Scheme

const swipeColors = {
liked: "#22c55e", // Green
disliked: "#ef4444", // Red
skipped: "#6b7280", // Gray
editAction: "#3b82f6", // Blue
deleteAction: "#ef4444", // Red
background: theme.background,
surface: theme.surface,
}

3. Animation & Gesture Patterns

// Using react-native-reanimated (already in use for AnimatedSwipeCard)
- PanGestureHandler for horizontal LEFT swipe detection only
- Native iOS-style reveal animation with spring physics
- Haptic feedback on action execution + success logging
- Visual feedback during swipe (action icons appear progressively)

4. Component Library & Design System

// Following existing patterns:
- Use NativeSheet for edit modal (like UsernameEditSheet/ReorderSheet)
- Button variants: will create new cell action button variant
- Colors: Use existing theme colors (destructive, primary, muted, etc.)
- Success feedback: Haptic + console logging (future toast integration)

5. Swipe Action Specifications

// RIGHT-SIDE REVEAL (iOS native pattern):
const SWIPE_ACTIONS = [
{ id: "edit", icon: "pencil", color: "primary", width: 80 },
{ id: "delete", icon: "trash", color: "destructive", width: 80 },
{ id: "rate", icon: "star", color: "amber", width: 80 },
{ id: "like", icon: "heart", color: "liked/disliked", width: 80 },
{ id: "details", icon: "eye", color: "muted", width: 80 }
]

// Actions behavior:
- Edit → NativeSheet with form (like EditSwipeDialog pattern)
- Delete → Immediate deletion with haptic + log
- Rate → Cycle through score ranges (1-3, 4-6, 7-8, 9-10)
- Like → Toggle liked(true)disliked(false)neutral(null)
- Details → Navigate to movie detail page

📱 Component Architecture

File Structure

app/swipe/
├── swipehistory.tsx # Main screen
├── components/
│ ├── SwipeHistoryList.tsx # Main list component
│ ├── SwipeHistoryRow.tsx # Individual row
│ ├── SwipeHistoryFilters.tsx # Filter controls
│ ├── SwipeHistoryActions.tsx # Swipe action buttons
│ └── SwipeHistoryEmpty.tsx # Empty states
├── modals/
│ ├── EditSwipeModal.tsx # Edit swipe modal
│ ├── DeleteSwipeModal.tsx # Delete confirmation
│ └── SwipeDetailModal.tsx # Full movie details
├── hooks/
│ ├── useSwipeHistory.ts # Data fetching
│ ├── useSwipeActions.ts # CRUD operations
│ └── useSwipeGestures.ts # Gesture handling
└── stores/
└── useSwipeHistoryStore.ts # Filter/sort state

Component Props Interface

// Main screen props
interface SwipeHistoryScreenProps {
initialFilter?: "liked" | "skipped" | "all"
}

// List component props
interface SwipeHistoryListProps {
data: InfiniteData<SwipeHistoryResponse>
onRefresh: () => void
onLoadMore: () => void
onSwipeAction: (action: SwipeAction, swipe: SwipeWithDetails) => void
isLoading: boolean
isRefreshing: boolean
}

// Row component props
interface SwipeHistoryRowProps {
swipe: SwipeWithDetails
onSwipeStart: () => void
onSwipeComplete: (action: SwipeAction) => void
onPress: () => void
}

🚀 Implementation Phases

Phase 1: Foundation (Week 1)

  • Basic FlatList implementation
  • Simple row component with movie data
  • Basic API integration with pagination
  • Loading and error states
  • Pull-to-refresh functionality

Phase 2: Core Features (Week 2)

  • Search and basic filtering
  • Sort functionality
  • Edit modal implementation
  • Delete functionality with confirmation
  • Optimistic UI updates

Phase 3: Advanced UX (Week 3)

  • Swipe gesture implementation
  • Action reveal animations
  • Haptic feedback integration
  • Advanced filtering (date, genre, score)
  • Empty states and error handling

Phase 4: Polish & Optimization (Week 4)

  • Performance optimizations
  • Accessibility improvements
  • Gesture refinements
  • Animation polish
  • Comprehensive testing

⚡ Feasibility Assessment

Highly Feasible

  • Backend API: Fully featured and ready
  • Data richness: All required fields available
  • React Native ecosystem: Excellent gesture libraries available
  • Performance: FlatList + React Query = smooth experience
  • Existing patterns: Can leverage web implementation patterns

🎯 Implementation Complexity: Medium

  • Swipe gestures: Well-documented with react-native-gesture-handler
  • Animation system: react-native-reanimated v3 provides excellent tools
  • State management: React Query + Zustand (already in use)
  • Testing: Jest + React Native Testing Library

🚧 Potential Challenges

  1. Gesture conflicts: Ensure swipe gestures don't interfere with navigation
  2. Performance at scale: Large lists need careful optimization
  3. Cross-platform consistency: Gesture behavior differs iOS/Android
  4. Accessibility: Swipe actions need alternative access methods

Backend Enhancements (Optional)

// Add to existing API - batch operations
POST /api/swipes/batch
{
"operations": [
{ "id": "uuid1", "action": "delete" },
{ "id": "uuid2", "action": "update", "data": { "score": 8 } }
]
}

Performance Enhancements

// Implement virtual scrolling for massive lists
import { VirtualizedList } from "react-native"

// Add image prefetching for smooth scrolling
import FastImage from "react-native-fast-image"

Analytics Integration

// Track user interactions for UX insights
- Swipe gesture usage vs button taps
- Most common filter combinations
- Edit vs delete action frequency
- Search query patterns

📋 Next Steps

Immediate Actions

  1. Create base SwipeHistoryScreen component
  2. Implement basic FlatList with API integration
  3. Add search and filter controls
  4. Create edit/delete modals

Dependencies to Install

# Gesture handling
npm install react-native-gesture-handler react-native-reanimated

# Image handling
npm install react-native-fast-image

# Haptic feedback
npm install react-native-haptic-feedback

# Date handling (for filters)
npm install date-fns

Testing Strategy

// Unit tests
- Gesture calculations
- Filter logic
- API integration
- State management

// Integration tests
- Complete user flows
- Error scenarios
- Performance benchmarks
- Accessibility compliance

🎉 Expected User Experience

Core User Journey

  1. Enter swipe history → See clean list of all swipes
  2. Search for movie → Instant filtered results
  3. Swipe row left → Reveal edit/delete actions smoothly
  4. Tap edit → Modal opens with current settings
  5. Update rating → Optimistic UI update, smooth save
  6. Pull to refresh → Latest swipes appear with animation

Success Metrics

  • Performance: 60fps scrolling, under 100ms gesture response
  • Usability: under 2 taps to complete any action
  • Discoverability: Swipe actions obvious within first use
  • Reliability: Offline capability, robust error recovery

This plan leverages the robust backend infrastructure already in place and follows React Native best practices for a smooth, performant user experience.